#include "Channel.hpp"
#include "EventLoop.hpp"
#include "Logger.hpp"

#include <sys/epoll.h>

const int Channel::kNoneEvent =0;
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI;
const int Channel::kWriteEvent = EPOLLOUT;

Channel::Channel(EventLoop *loop,int fd)
   :loop_(loop),fd_(fd),events_(0),revents_(0),index_(-1),tied_(false)
{
}

Channel::~Channel()
{
}

/**
 * 一个TcpConnection新连接创建的时候 (TcpConnection => Channel)
 * 防止当TcpConnection销毁的时候，Channel还在监听其事件
 */
void Channel::tie(const std::shared_ptr<void> &obj)
{
    tie_=obj;
    tied_=true;
}

/**
 * 但改变channel所表示fd的events事件后，update负责在poller里面更改fd相应的事件epoll_ctl
 */
void Channel::update()
{
    //通过channel所属的EventLoop,调用poller的相应方法，注册fd的events事件
    loop_->updateChannel(this);
}

//在channel所属的EventLoop中，把当前的channel删除掉
void Channel::remove()
{
    loop_->removeChannel(this);
}

// fd得到poller通知以后，处理事件的
void Channel::handleEvent(Timestamp receiveTime)
{
    std::shared_ptr<void> guard;
    if(tied_)
    {
        guard=tie_.lock(); //lock将weak_ptr提升至shared_ptr
        if(guard)
        {
            handleEventWithGuard(receiveTime);
        }
    }
    else
    {
        handleEventWithGuard(receiveTime);
    }
}

// 根据poller通知的channel发生的具体事件，由channel负责调用具体的回调操作
void Channel::handleEventWithGuard(Timestamp receiveTime)
{
    LOG_INFO("channel handleEvent revents:%d",revents_);

    if((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN))
    {
        if(closeCallback_)
        {
            closeCallback_();
        }
    }

    if(revents_ & EPOLLERR)
    {
        if(errorCallback_)
        {
            errorCallback_();
        }
    }

    if(revents_ & (EPOLLIN | EPOLLPRI))
    {
        if(readCallback_)
        {
            readCallback_(receiveTime);
        }
    }

    if(revents_ & EPOLLOUT)
    {
        if(writeCallback_)
        {
            writeCallback_();
        }
    }
}